﻿#include "cdatabaseopermgr_private.h"

const QString READ_CONNECT_NAME = "DatabaseOperRead";              //读连接名称
const QString WRITE_CONNECT_NAME = "DatabaseOperwrite";            //写连接名称
const int DEFAULT_READ_CONNECT_NUMBER = 6;                     //默认读连接数量
const int DEFAULT_WRITE_CONNECT_NUMBER = 4;                    //默认写连接数量
const int TRY_LOCK_TIME = 10;                                  //尝试加锁时间，单位ms
const int WRITE_SQL_LOOP_TIME = 10;                            //同表写数据库周期时间，单位ms
const int g_nRetryNum = 3;                                     //尝试取得线程锁次数，超出则退出

CDatabaseOperMgrPrivate::CDatabaseOperMgrPrivate()
{
    m_bIsOpen = false;
    m_bIsSetNumber = false;
    m_nReadNumber = DEFAULT_READ_CONNECT_NUMBER;
    m_nWriteNumber = DEFAULT_WRITE_CONNECT_NUMBER;
    m_vecReadDbOper.clear();
    m_vecWriteDbOper.clear();
    m_listTableName.clear();
    m_pLog = nullptr;
    m_vecDbDataInfo.clear();
    m_mapTransID.clear();
    m_mapTransSql.clear();
    m_pDbOpenDoneCb = nullptr;
}

CDatabaseOperMgrPrivate::~CDatabaseOperMgrPrivate()
{
    close();
}

bool CDatabaseOperMgrPrivate::setConnectNumber(const quint8 &nReadNum, const quint8 &nWriteNum)
{
    if (m_bIsSetNumber)
    {
        return false;
    }

    if (0 == nReadNum)
    {
        return false;
    }

    if (0 == nWriteNum)
    {
        return false;
    }
    m_nReadNumber = nReadNum;
    m_nWriteNumber = nWriteNum;
    m_bIsSetNumber = true;
    return true;
}

bool CDatabaseOperMgrPrivate::setDbConfigInfo(const CDataBaseConfig &stDbCfg)
{
    //入参判断
    if(stDbCfg.sIP.isEmpty()
            || stDbCfg.nPort < 0 || stDbCfg.nPort > 65535
            || stDbCfg.sName.isEmpty()
            || stDbCfg.sDBType.isEmpty()
            || stDbCfg.sUserName.isEmpty()) return false;

    m_stDbCfg = stDbCfg;
    return true;
}

bool CDatabaseOperMgrPrivate::setDbConfigInfo(const CDataBaseConfig &stDbCfg, QVector<QString> vecTableName)
{
    bool bRet = setDbConfigInfo(stDbCfg);
    if(false == bRet) return false;
    if (vecTableName.isEmpty()) return false;
    bRet = false;
    for (int i = 0; i < vecTableName.size(); i++)
    {
        if (vecTableName.at(i).isEmpty()) continue;
        CDbTableInfoMgr *pInfo = new CDbTableInfoMgr;
        pInfo->m_sTableName = vecTableName.at(i);
        m_vecDbDataInfo.push_back(pInfo);
        bRet = true;
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::setDbConfigInfo(const CDataBaseConfig &stDbCfg, QStringList listTableName)
{
    bool bRet = setDbConfigInfo(stDbCfg);
    if(false == bRet) return false;
    if (listTableName.isEmpty()) return false;
    bRet = false;
    for (int i = 0; i < listTableName.size(); i++)
    {
        if (listTableName.at(i).isEmpty()) continue;
        CDbTableInfoMgr *pInfo = new CDbTableInfoMgr;
        pInfo->m_sTableName = listTableName.at(i);
        m_vecDbDataInfo.push_back(pInfo);
        bRet = true;
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::setDbConfigInfo(const CDataBaseConfig &stDbCfg, QVector<CDbTableInfo> vecTableInfo)
{
    bool bRet = setDbConfigInfo(stDbCfg);
    if(false == bRet) return false;
    if (vecTableInfo.isEmpty()) return false;
    bRet = false;
    for (int i = 0; i < vecTableInfo.size(); i++)
    {
        if (vecTableInfo.at(i).sTableName.isEmpty()) continue;
        CDbTableInfoMgr *pInfo = new CDbTableInfoMgr;
        pInfo->m_sMode = vecTableInfo.at(i).sMode;
        pInfo->m_sTableName = vecTableInfo.at(i).sTableName;
        m_vecDbDataInfo.push_back(pInfo);
        bRet = true;
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::open()
{
    //以防多次调用打开数据库
    if (m_bIsOpen)
    {
        return true;
    }

    //创建读连接
    if(m_vecReadDbOper.isEmpty())
    {
		QString sConStr = m_stDbCfg.sConnectName;
        int nReadNumber = m_nReadNumber;
        for (int i = 0; i < nReadNumber; ++i)
        {
            m_stDbCfg.sConnectName = QString("%1%2").arg(READ_CONNECT_NAME).arg(i)+ sConStr;
            CDbBaseOper *pDatabase = CDbBaseOper::createCDbSqlOper(m_stDbCfg);
            if (nullptr != pDatabase && pDatabase->open())
            {
                pDatabase->setLogPtr(m_pLog);
                m_vecReadDbOper.append(pDatabase);
                writeLog(QObject::tr("[Create Database Connection] %1 read connection Create Successed")
                         .arg(pDatabase->m_db.connectionName()), CLogBase::enLevelInfo, def_FL);
            }
            else
            {
                if(nullptr != pDatabase)
                {
                    writeLog(QObject::tr("[Create Database Connection] %1 Read Connection Create Failed, %2")
                             .arg(pDatabase->m_db.connectionName())
                             .arg(pDatabase->m_db.lastError().text()),
                             CLogBase::enLevelAlarm, def_FL);
                    delete pDatabase;
                }
                return false; //创建失败退出，等待下个循环
            }
        }
    }

    //创建写连接
    if(m_vecWriteDbOper.isEmpty())
    {
		QString sConStr = m_stDbCfg.sConnectName;
        int nWriteNumber = m_nWriteNumber;
        for (int i = 0; i < nWriteNumber; ++i)
        {
            m_stDbCfg.sConnectName = QString("%1%2").arg(WRITE_CONNECT_NAME).arg(i) + sConStr;
            CDbBaseOper *pDatabase = CDbBaseOper::createCDbSqlOper(m_stDbCfg);
            if (nullptr != pDatabase && pDatabase->open())
            {
                pDatabase->setLogPtr(m_pLog);
                m_vecWriteDbOper.append(pDatabase);
                writeLog(QObject::tr("[Create Database Connection] %1 Write Connection Create Successed")
                         .arg(pDatabase->m_db.connectionName()), CLogBase::enLevelInfo, def_FL);
            }
            else
            {
                if(nullptr != pDatabase)
                {
                    writeLog(QObject::tr("[Create Database Connection] %1 Write Connection Create Failed, %2")
                             .arg(pDatabase->m_db.connectionName())
                             .arg(pDatabase->m_db.lastError().text()),
                             CLogBase::enLevelAlarm, def_FL);
                    delete pDatabase;
                }
                break;
            }
        }
    }

    if(m_nReadNumber != m_vecReadDbOper.size() ||
            m_nWriteNumber != m_vecWriteDbOper.size())
    {
        //数据库连接失败 则释放数据库资源
        close();
        return false;
    }

    m_bIsOpen = true;
    return true;
}

void CDatabaseOperMgrPrivate::close()
{
    m_bIsOpen = false;
    //清空读连接
    QVector<CDbBaseOper*> vec = m_vecReadDbOper;
    m_vecReadDbOper.clear();
    for(int i=0; i<vec.size(); ++i)
    {
        CDbBaseOper *pDb = vec.at(i);
        if(nullptr != pDb)
        {
            QString sConnectName = pDb->m_db.connectionName();
            pDb->m_db.close();
            delete pDb;
            pDb = nullptr;
            QSqlDatabase::removeDatabase(sConnectName);
        }
    }
    //清空写连接
    vec = m_vecWriteDbOper;
    m_vecWriteDbOper.clear();
    for(int i=0; i<vec.size(); ++i)
    {
        CDbBaseOper *pDb = vec.at(i);
        if(nullptr != pDb)
        {
            QString sConnectName = pDb->m_db.connectionName();
            pDb->m_db.close();
            delete pDb;
            pDb = nullptr;
            QSqlDatabase::removeDatabase(sConnectName);
        }
    }
    //释放数据库表信息
    QVector<CDbTableInfoMgr*> vecInfo = m_vecDbDataInfo;
    m_vecDbDataInfo.clear();
    foreach (CDbTableInfoMgr *pInfo, vecInfo)
    {
        if(nullptr == pInfo) continue;
        delete pInfo;
        pInfo = nullptr;
    }
}

bool CDatabaseOperMgrPrivate::isOpen()
{
    bool bReturn = false;
    //判断读连接状态，断开自动重连
    bReturn = reconnect(m_vecReadDbOper);
    //判断写连接状态，断开自动重连
    bReturn = reconnect(m_vecWriteDbOper);
    return bReturn;
}

bool CDatabaseOperMgrPrivate::transaction(const QString &strId, int nType)
{
    if(m_mapTransID.contains(strId)) return true;
    bool bRet = false;
    switch (nType)
    {
    case CDatabaseOperMgr::enDBRead:
        bRet = connectTransaction(strId, m_vecReadDbOper);
        break;
    case CDatabaseOperMgr::enDBWrite:
        bRet = connectTransaction(strId, m_vecWriteDbOper);
        break;
    default:
        break;
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::commit(const QString &strId)
{
    if(false == m_mapTransID.contains(strId)) return true;
    CDbBaseOper *pDb = m_mapTransID.value(strId);
    bool bRet = pDb->m_db.commit();
    //提交成功，移除事务连接
    if(bRet)
    {
        m_mapTransID.remove(strId);
        m_mapTransSql.remove(pDb);
    }
    else
    {
        //提交失败，回滚
        pDb->m_db.rollback();
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::rollback(const QString &strId)
{
    if(false == m_mapTransID.contains(strId)) return false;
    CDbBaseOper *pDb = m_mapTransID.value(strId);
    bool bRet = pDb->m_db.rollback();
    //回滚后，不管成功与否，移除事务连接
    m_mapTransID.remove(strId);
    m_mapTransSql.remove(pDb);
    return bRet;
}

CDbTableDataInfo *CDatabaseOperMgrPrivate::getDbDataInfo(const int &nTable, const int nType)
{
    if((nTable < 0) || (nTable >= m_vecDbDataInfo.size()))
    {
        return nullptr;
    }
    CDbTableInfoMgr *pInfo = m_vecDbDataInfo.at(nTable);
    int nNum = 0;
    while(1)
    {
        //对资源进行锁定
        if(pInfo->tryLock(TRY_LOCK_TIME)) break;
        nNum++;
        //尝试次数到达则退出，否则线程可能死锁
        if (nNum > g_nRetryNum)
        {
            pInfo = nullptr;
            break;
        }
        //资源阻塞式访问
        if(enBLOCK == nType) continue;
        //非阻塞式访问
        pInfo = nullptr;
        break;
    }
    //清空资源
    if(nullptr != pInfo) pInfo->resetInfo();
    return pInfo;
}

CDbTableDataInfo *CDatabaseOperMgrPrivate::getDbDataInfo(const QString &strTable, const int nType)
{
    for (int i=0; i<m_vecDbDataInfo.size(); ++i)
    {
        CDbTableInfoMgr *pInfo = m_vecDbDataInfo.at(i);
        if(pInfo->m_sTableName != strTable) continue;
        return getDbDataInfo(i, nType);
    }
    return nullptr;
}

bool CDatabaseOperMgrPrivate::getResult(const int &nTable, const int &nLock)
{
    if((nTable < 0) || (nTable >= m_vecDbDataInfo.size()))
    {
        writeLog(QObject::tr("[Database Operate] Table index exception, Table not found"),
                 CLogBase::enLevelAlarm, def_FL);
        return false;
    }
    bool bRet = false;
    CDbTableInfoMgr *pInfo = m_vecDbDataInfo.at(nTable);
    //Sql类型判断
    switch (pInfo->m_nWorkType)
    {
    case enSQLSELECT:
        bRet = execRead(pInfo);
        break;
    case enSQLUPDATE:
    case enSQLINSERT:
    case enSQLDELETE:
    case enSQLCREATE:
    case enSQLINSERTBATCH:
    case enSQLCUSTOM:
        bRet = execWrite(pInfo);
        break;
    default:
        break;
    }
    //资源锁判断
    switch (nLock) {
    case enLockNORMAL:
        //默认模式，自动解锁
        pInfo->unlock();
        break;
    case enLockSELECT:
        //非查询语句执行完成，或者语句执行失败，直接释放资源锁（查询语句可能需要解析数据，需要解析数据后手动释放）
        if((enSQLSELECT != pInfo->m_nWorkType &&
            enSQLSELECT != pInfo->m_nSqlType) || false == bRet)
            pInfo->unlock();
        break;
    case enLockALWAYS:
    default:
        //手动释放资源锁
        break;
    }
    QString sLog = "";
    if (2 == pInfo->m_listErr.size())
    {
        sLog = QString("sql : %1, ").arg(pInfo->m_listErr.at(0));
        sLog += QString("error : %1").arg(pInfo->m_listErr.at(1));
    }
    if (false == bRet) writeLog(sLog, CLogBase::enLevelAlarm, def_FL);
    return bRet;
}

bool CDatabaseOperMgrPrivate::getResult(const QString &strTable, const int &nLock)
{
    for (int i=0; i<m_vecDbDataInfo.size(); ++i)
    {
        CDbTableInfoMgr *pInfo = m_vecDbDataInfo.at(i);
        if(pInfo->m_sTableName != strTable) continue;
        return getResult(i, nLock);
    }
    writeLog(QObject::tr("[Database Operate] Table '%1' not found, please confirm table name configuration is correct")
             .arg(strTable), CLogBase::enLevelAlarm, def_FL);
    return false;
}

void CDatabaseOperMgrPrivate::writeLog(const QString &sLogText, int nType, const QString &sFl)
{
    if(nullptr == m_pLog)
    {
        qDebug() << QObject::tr("[Database][%1:%2] : %3")
                    .arg(sFl).arg(nType).arg(sLogText);
        return;
    }
    m_pLog->writeLog(QObject::tr("Database Module"), sLogText, nType, sFl, 0);
}

bool CDatabaseOperMgrPrivate::reconnect(QMap<QMutex *, CDbBaseOper *> mapDb)
{
    bool bReturn = false;
    auto iteratorWrite = mapDb.constBegin();
    while (iteratorWrite != mapDb.constEnd())
    {
        QMutex *pMutex = iteratorWrite.key();
        CDbBaseOper *pDatabase = iteratorWrite.value();
        if (pMutex->tryLock(TRY_LOCK_TIME))
        {
            bReturn = pDatabase->isOpen();
            if (!bReturn)
            {
                writeLog(QObject::tr("[Database Reconnection] %1 disconnet, prepare for reconnection")
                         .arg(pDatabase->m_db.connectionName()),
                         CLogBase::enLevelAlarm, def_FL);
                pDatabase->m_db.close();
                bReturn = pDatabase->m_db.open();
                if (!bReturn)
                {
                    writeLog(QObject::tr("[Database Reconnection] Write reconnection failed, Reason : %1")
                             .arg(pDatabase->m_db.lastError().text()),
                             CLogBase::enLevelAlarm, def_FL);
                }
                else
                {
                    writeLog(QObject::tr("[Database Reconnection] %1 reconnection successed")
                             .arg(pDatabase->m_db.connectionName()),
                             CLogBase::enLevelInfo, def_FL);
                }
                pMutex->unlock();
            }
            else
            {
                pMutex->unlock();
                break;
            }
        }
        else
        {
            bReturn = true;
        }

        ++iteratorWrite;
    }
    return bReturn;
}

bool CDatabaseOperMgrPrivate::reconnect(QVector<CDbBaseOper *> vecDb)
{
    bool bReturn = false;
    for(int i=0; i<vecDb.size(); ++i)
    {
        CDbBaseOper *pDb = vecDb.at(i);
        if(pDb->tryLock(TRY_LOCK_TIME))
        {
            bReturn = pDb->isOpen();
            if (!bReturn)
            {
                writeLog(QObject::tr("[Database Reconnection] %1 disconnet, prepare for reconnection")
                         .arg(pDb->m_db.connectionName()),
                         CLogBase::enLevelAlarm, def_FL);
                pDb->m_db.close();
                bReturn = pDb->m_db.open();
                if (!bReturn)
                {
                    writeLog(QObject::tr("[Database Reconnection] %1 reconnection failed, Reason : %2")
                             .arg(pDb->m_db.connectionName())
                             .arg(pDb->m_db.lastError().text()),
                             CLogBase::enLevelAlarm, def_FL);
                }
                else
                {
                    writeLog(QObject::tr("[Database Reconnection] %1 reconnection successed")
                             .arg(pDb->m_db.connectionName()),
                             CLogBase::enLevelInfo, def_FL);
                }
                pDb->unlock();
            }
            else
            {
                pDb->unlock();
            }
        }
        else bReturn = true;
    }
    return bReturn;
}

bool CDatabaseOperMgrPrivate::connectTransaction(const QString &strId, QMap<QMutex *, CDbBaseOper *> mapDb)
{
    bool bRet = false;
    auto it = mapDb.constBegin();
    while ( it != mapDb.constEnd() )
    {
        QMutex *pMutex = it.key();
        CDbBaseOper *pDatabase = it.value();
        if (pMutex->tryLock(TRY_LOCK_TIME))
        {
            //此连接已开启事务，寻找下一个
            if(m_mapTransSql.contains(pDatabase))
            {
                pMutex->unlock();
                ++it;
                if (it == mapDb.constEnd())
                {
                    it = mapDb.constBegin();
                }
                continue;
            }
            bRet = pDatabase->m_db.transaction();
            //开启事务失败，寻找下一个
            if(false == bRet)
            {
                pMutex->unlock();
                ++it;
                if (it == mapDb.constEnd())
                {
                    it = mapDb.constBegin();
                }
                continue;
            }
            //事务开启成功
            m_mapTransID.insert(strId, pDatabase);
            m_mapTransSql.insert(pDatabase, strId);
            pMutex->unlock();
            break;
        }
        ++it;
        if (it == mapDb.constEnd())
        {
            it = mapDb.constBegin();
        }
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::connectTransaction(const QString &strId, QVector<CDbBaseOper *> vecDb)
{
    bool bRet = false;
    for(int i=0; i<vecDb.size(); )
    {
        CDbBaseOper *pDb = vecDb.at(i);
        if (pDb->tryLock(TRY_LOCK_TIME))
        {
            //此连接已开启事务，寻找下一个
            if(m_mapTransSql.contains(pDb))
            {
                pDb->unlock();
                ++i;
                //if (i == vecDb.size()) i=0;
                continue;
            }
            bRet = pDb->m_db.transaction();
            //开启事务失败，寻找下一个
            if(false == bRet)
            {
                pDb->unlock();
                ++i;
                //if (i == vecDb.size()) i=0;
                continue;
            }
            //事务开启成功
            m_mapTransID.insert(strId, pDb);
            m_mapTransSql.insert(pDb, strId);
            pDb->unlock();
            break;
        }
        ++i;
        //if (i == vecDb.size()) i=0;
    }
    return bRet;
}

bool CDatabaseOperMgrPrivate::execRead(CDbTableInfoMgr *pMgr)
{
    if(false == m_bIsOpen)
    {
        return false;
    }
    //事务判断
    if(false == pMgr->m_sTransactionID.isEmpty())
    {
        return execTransactionRead(pMgr);
    }

    bool bReturn = false;
    for(int i=0; i<m_vecReadDbOper.size(); )
    {
        CDbBaseOper *pDb = m_vecReadDbOper.at(i);
        if (false == pDb->tryLock(TRY_LOCK_TIME))
        {
            ++i;
            if(i == m_vecReadDbOper.size()) i=0;
            continue;
        }
        bReturn = getSqlData(pDb, pMgr);
        pDb->unlock();
        break;
    }
    return bReturn;
}

bool CDatabaseOperMgrPrivate::execWrite(CDbTableInfoMgr *pMgr)
{
    if(false == m_bIsOpen)
    {
        return false;
    }
    //事务判断
    if(false == pMgr->m_sTransactionID.isEmpty())
    {
        return execTransactionWrite(pMgr);
    }

    bool bReturn = false;
    for(int i=0; i<m_vecWriteDbOper.size(); )
    {
        CDbBaseOper *pDb = m_vecWriteDbOper.at(i);
        if (false == pDb->tryLock(TRY_LOCK_TIME))
        {
            ++i;
            if(i == m_vecWriteDbOper.size()) i=0;
            continue;
        }
        bReturn = getSqlData(pDb, pMgr);
        pDb->unlock();
        break;
    }
    return bReturn;
}

bool CDatabaseOperMgrPrivate::execTransactionRead(CDbTableInfoMgr *pMgr)
{
    if(false == m_bIsOpen)
    {
        return false;
    }
    //事务判断
    if(pMgr->m_sTransactionID.isEmpty())
    {
        return execRead(pMgr);
    }

    bool bReturn = false;

    //未找到事务执行连接，返回失败
    if(false == m_mapTransID.contains(pMgr->m_sTransactionID)) return false;
    CDbBaseOper *pDb = m_mapTransID.value(pMgr->m_sTransactionID);
    while(1)
    {
        //尝试加锁
        if (false == pDb->tryLock(TRY_LOCK_TIME))
        {
            //尝试加锁失败
            QEventLoop loop;
            QTimer::singleShot(WRITE_SQL_LOOP_TIME, &loop, SLOT(quit()));
            loop.exec();
            continue;
        }
        bReturn = getSqlData(pDb, pMgr);
        pDb->unlock();
        break;
    }

    return bReturn;
}

bool CDatabaseOperMgrPrivate::execTransactionWrite(CDbTableInfoMgr *pMgr)
{
    if(false == m_bIsOpen)
    {
        return false;
    }
    //事务判断
    if(pMgr->m_sTransactionID.isEmpty())
    {
        return execWrite(pMgr);
    }

    bool bReturn = false;
    while(true)
    {
        m_lockTableName.lockForRead();
        if (m_listTableName.contains(pMgr->m_sTableName))
        {
            m_lockTableName.unlock();
            QEventLoop loop;
            QTimer::singleShot(WRITE_SQL_LOOP_TIME, &loop, SLOT(quit()));
            loop.exec();
            continue;
        }
        m_lockTableName.unlock();
        //未找到事务执行连接，返回失败
        if(false == m_mapTransID.contains(pMgr->m_sTransactionID)) return false;
        CDbBaseOper *pDb = m_mapTransID.value(pMgr->m_sTransactionID);
        while(1)
        {
            //尝试加锁
            if (false == pDb->tryLock(TRY_LOCK_TIME))
            {
                //尝试加锁失败
                QEventLoop loop;
                QTimer::singleShot(WRITE_SQL_LOOP_TIME, &loop, SLOT(quit()));
                loop.exec();
                continue;
            }
            //写数据库加锁
            AppendTableName(pMgr->m_sTableName);
            bReturn = getSqlData(pDb, pMgr);
            pMgr->m_sTransactionID = "";
            RemoveTableName(pMgr->m_sTableName);
            pDb->unlock();
            break;
        }
        break;
    }

    return bReturn;
}

void CDatabaseOperMgrPrivate::AppendTableName(const QString &sTableName)
{
    m_lockTableName.lockForWrite();
    m_listTableName.append(sTableName);
    m_lockTableName.unlock();
}

void CDatabaseOperMgrPrivate::RemoveTableName(const QString &sTableName)
{
    m_lockTableName.lockForWrite();
    if (!m_listTableName.isEmpty())
    {
        m_listTableName.removeOne(sTableName);
    }
    m_lockTableName.unlock();
}

bool CDatabaseOperMgrPrivate::getSqlData(CDbBaseOper *pDb, CDbTableInfoMgr *pMgr)
{
    //判断数据是否初始化
    if(false == pMgr->m_bInitRecord)
    {
        if(false == initSqlData(pDb, pMgr))
            return pMgr->m_bSqlOperIsOk;
    }
    pDb->handleSql(pMgr);
    return pMgr->m_bSqlOperIsOk;
}

bool CDatabaseOperMgrPrivate::initSqlData(CDbBaseOper *pDb, CDbTableInfoMgr *pMgr)
{
    pDb->initTableInfo(pMgr);
    if (pMgr->m_bSqlOperIsOk)
    {
        pMgr->m_bInitRecord = true;
        return true;
    }
    return false;
}

